<?php

class Personage {

    private $strengs, 
            $dexterity, 
            $intelligence, 
            $constitution, 
            $luck, 
            $armor, 
            $weapon, 
            $personage_type, // 1 - Warior(50), 2 - Mage(10), 3 - Ranger(25)
            $lvl,
            $hp;

    function __construct($character_data) {
        $this->personage_type = $character_data[29];
        $this->lvl = $character_data[7];
        $this->strengs = $character_data[35] + $character_data[30];
        $this->dexterity = $character_data[36] + $character_data[31];
        $this->intelligence = $character_data[37] + $character_data[32];
        $this->luck = $character_data[39] + $character_data[34];
        $this->constitution = $character_data[38] + $character_data[33];
        $this->armor = $character_data[447];
        $this->weapon = new stdClass();
        $this->weapon->min_damage = $character_data[146];
        $this->weapon->max_damage = $character_data[147];
        
        switch ($this->personage_type) {
            case 1: $k = 5; break;
            case 2: $k = 2; break;
            case 3: $k = 4; break;
        }
        $this->hp = $this->constitution * $k * ($this->lvl + 1);
    }
    
    function getClassName() {
        switch ($this->personage_type) {
            case 1: return 'Warior';
                break;
            case 3: return 'Ranger';
                break;
            case 2: return 'Mage';
                break;
        }
    }
    
    function getClass() {
        switch ($this->personage_type) {
            case 1: return 1;
                break;
            case 3: return 3;
                break;
            case 2: return 2;
                break;
        }
    }
    
    function getHP() {
        return $this->hp;
    }
    
    function WeaponMin(){
        return $this->weapon->min_damage;
    }
    
    function WeaponMax(){
        return $this->weapon->max_damage;
    }
    
    function PrimaryAttr(){
        switch ($this->personage_type) {
            case 1: return $this->strengs; break;
            case 2: return $this->intelligence; break;
            case 3: return $this->dexterity; break;
        }
    }
    
    function PrimaryAttrTitle(){
        switch ($this->personage_type) {
            case 1: return "Strengs"; break;
            case 2: return "Intelligence"; break;
            case 3: return "Dexterity"; break;
        }
    }
    
    function getStrengs(){
        return $this->strengs;
    }
    function getIntelligence(){
        return $this->intelligence;
    }
    function getDexterity(){
        return $this->dexterity;
    }
    
    function ifCrit($oponent_lvl){
        $rand = rand(0, 10000);
        $k = 1;
        $krit = $this->luck*5/($oponent_lvl*2);
        if($krit>50) $krit = 50;
        $krit = $krit*100;
        if( $rand < $krit ) 
           $k = 2;
        return $k;
    }
    
    function setHit($hit, $oponent_class) {
        //TODO
        if($this->personage_type == "2" || $oponent_class == "2"){
            $this->hp = $this->hp - $hit;
        } elseif($this->personage_type == "3") {
            $rand = rand(0, 100);
            if( $rand>50 ) $this->hp = $this->hp - $hit;
        } elseif($this->personage_type == "1") {
            $rand = rand(0, 100);
            if( $rand>25 ) $this->hp = $this->hp - $hit;
        } 
    }
    function getLvl(){
        return $this->lvl;
    }
    
    function getBlock($oponent){
        //TODO
    }
    function getArmor($oponent){
        
        $armor = $this->armor/$oponent->getLvl();
        if($this->personage_type == 1 && $armor>50) $armor = 50;
        if($this->personage_type == 2 && $armor>10) $armor = 10;
        if($this->personage_type == 3 && $armor>25) $armor = 25;
        if( $oponent->getClass() == 2 ) return 1;
        else return 1 - ($armor/100);
    }
    function getRes($oponent){
        if($this->personage_type == $oponent->getClass()){
            return 0;
        } else {
            $attr = "get".$this->PrimaryAttrTitle()."()";
            return $oponent->$attr/20;
        }
    }
}

class SF_Calc {
    private $keys = array(
                "MyHP" => "\$pers1->getHP()",
                "MyMinDmg" => "\$pers1->WeaponMin()",
                "MyMaxDmg" => "\$pers1->WeaponMax()",
                "MyPrmAttr" => "\pers1->PrimaryAttr()",
                "MyRes" => "\$pers1->GetRes(\$pers2)",
                "MyArm" => "\$pers1->GetArm(\$pers2)",
                "OpHP" => "\$pers2->getHP()",
                "OpMinDmg" => "\$pers2->WeaponMin()",
                "OpMaxDmg" => "\$pers2->WeaponMax()",
                "OpRes" => "\$pers2->GetRes(\$pers1)",
                "OpArm" => "\$pers2->GetArm(\$pers1)",
                "OpBlock" => "\$pers2->GetBlock(\$pers1)",
                "Rnd" => "\$Rnd",

            ),
            $test = "( random ( MyMinDmg * ( 1 + ( Rnd - 1 ) * 0.4 ), MyMaxDmg * ( 1 + ( Rnd - 1 ) * 0.4 ) ) ) * ( 1 + ( MyPrmAttr / 10 ) - OpRes ) * ( MyIfCrit ) * ( OpArm ) * ( OpBlock )";
    public static function CalculateWin($personage1 , $personage2) {
        $pers1_wins = 0;
        $pers2_wins = 0;
        $i = 0;
        
        while($i<500){
            $pers1 = clone $personage1;
            $pers2 = clone $personage2;
            $damage_k = 1;
            $Rnd = 1;
            while ($pers1->getHp() > 0 && $pers2->getHP() > 0){
                /*
                if($n>1 && $n<=4) $damage_k = 1.4;
                if($n>4 && $n<=6) $damage_k = 1.8;
                if($n>6)$damage_k += 0.4;
                */
                $hit = SF_Calc::getRandomDPS($pers1, $pers2, $Rnd)*$pers1->ifCrit($pers2->getLvl())*$pers2->getArmor($pers1);
                $pers2->setHit( $hit, $pers1->getClass() );
                if($pers2->getHP() <=0){ 
                    $pers1_wins++;
                    continue;
                }
                $hit = SF_Calc::getRandomDPS($pers2, $pers1, $Rnd)*$pers2->ifCrit($pers1->getLvl())*$pers1->getArmor($pers2);
                $pers1->setHit( $hit, $pers2->getClass() );
                if($pers1->getHP() <=0){ 
                    $pers2_wins++;
                    continue;
                }
                //$damage_k += 0.4;
                $Rnd++;
            }
            $i++;
        }
        $i = 0;
        
        $result = $pers1_wins;
        $pers1_wins = 0;
        $pers2_wins = 0;
        while($i<500){
            $pers1 = clone $personage2;
            $pers2 = clone $personage1;
            $damage_k = 1;
            $Rnd = 1;
            while ($pers1->getHp() > 0 && $pers2->getHP() > 0){
                /*
                if($n>1 && $n<=4) $damage_k = 1.4;
                if($n>4 && $n<=6) $damage_k = 1.8;
                if($n>6)$damage_k += 0.4;
                */
                $hit = SF_Calc::getRandomDPS($pers1, $pers2, $Rnd)*$pers1->ifCrit($pers2->getLvl())*$pers2->getArmor($pers1);
                $pers2->setHit( $hit, $pers1->getClass() );
                if($pers2->getHP() <=0){ 
                    $pers1_wins++;
                    continue;
                }
                $hit = SF_Calc::getRandomDPS($pers2, $pers1, $Rnd)*$pers2->ifCrit($pers1->getLvl())*$pers1->getArmor($pers2);
                $pers1->setHit( $hit, $pers2->getClass() );
                if($pers1->getHP() <=0){ 
                    $pers2_wins++;
                    continue;
                }
                //$damage_k += 0.4;
                $Rnd++;
            }
            $i++;
        }
        return ($pers2_wins+$result)/10;
        
    }
    
    private static function getRandomDPS($pers1, $pers2, $n){
        $k = 1 + ($n-1)*0.2;
        $dps = rand($pers1->WeaponMin()*$k, $pers1->WeaponMax()*$k);
        $attr = "get".$pers1->PrimaryAttrTitle()."()";
        return $dps *(1 + ($pers1->PrimaryAttr())/10 - $pers1->getRes($pers2));
    }
}
